/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "StdAfx.h"
#include "../Slider.h"

#include <sstream>

namespace gui {

Slider::Slider(void)
:	m_fMinValue(0),
	m_fMaxValue(10),
	m_fInterval(0),
	m_eDirection(HORIZONTAL),
	m_fCurrentValue(5),
	m_bDragging(false),
	m_bDrawLabels(true)
{
	m_pKnob = new gui::Button("");
	m_pKnob->setSize(8, 12);
	m_pKnob->addMouseListener(this);
	updateSliderOffset();
	add(m_pKnob);
}

Slider::~Slider(void)
{
}

void Slider::setDirection(eDirection dir)
{
	m_eDirection = dir;
}

void Slider::setRange(float minVal, float maxVal)
{
	m_fMinValue = minVal;
	m_fMaxValue = maxVal;
	updateSliderOffset();
}

void Slider::setMinValue(float val)
{
	m_fMinValue = val;
	updateSliderOffset();
}

void Slider::setMaxValue(float val)
{
	m_fMaxValue = val;
	updateSliderOffset();
}

void Slider::setInterval(float value)
{
	m_fInterval = value;
	updateSliderOffset();
}

void Slider::setCurrentValue(float val)
{
	m_fCurrentValue = val;
	updateSliderOffset();
}

const float Slider::getMinValue() const
{
	return m_fMinValue;
}

const float Slider::getMaxValue() const
{
	return m_fMaxValue;
}

const float Slider::getCurrentValue() const
{
	return m_fCurrentValue;
}

const float Slider::getInterval() const
{
	return m_fInterval;
}

void Slider::draw()
{
	if (bVisible) {
		vRealPos = getAbsolutePosition();
		int lineY = vRealPos.y + static_cast<int>(vDim.y/2.0);
		pRenderer->drawFilledRect(vRealPos.x, lineY-1, vDim.x-8, 3, vBorderColor);

		drawElements();

		if (m_bDrawLabels) {
			std::stringstream sstr;
			sstr<<m_fMinValue;
			font->print(sstr.str(), vRealPos.x, vRealPos.y+vDim.y-4, 0, FONT_LEFT, 0, 0, vTextColor);
			sstr.str(std::string());
			sstr<<m_fMaxValue;
			font->print(sstr.str(), vRealPos.x + vDim.x-10, vRealPos.y+vDim.y-4, 0, FONT_LEFT, 0, 0, vTextColor);
		}
	}
}

void Slider::setDimension(int x, int y, int w, int h)
{
	Component::setDimension(x, y, w, h);
	updateSliderOffset();
}

void Slider::setSize(int w, int h)
{
	Component::setSize(w, h);
	updateSliderOffset();
}

void Slider::updateSliderOffset()
{
	float diff = m_fMaxValue - m_fMinValue;
	float offset = m_fCurrentValue / diff;
	m_fSliderOffset = offset * (vDim.x-8);
 	m_pKnob->setPosition(static_cast<int>(m_fSliderOffset-4), 4);
	valueChanged(this);
}
void Slider::onMousePressEvent(const MouseEvent &mevent)
{
	m_bDragging = true;
}

void Slider::onMouseReleaseEvent(const MouseEvent &mevent)
{
	m_bDragging = false;
}

bool Slider::processMouse(int _x, int _y, int _z, int _button)
{
	static bool retval;
	static int off, round = 0;
	if (_button != iLastButton && _button != -1) {
		m_bDragging = false;
	}

	retval = Component::processMouse(_x, _y, _z, _button);

	if (m_bDragging) {
		off = _x - getAbsolutePosition().x;
		if (off != 0) {
			m_fCurrentValue = off * (m_fMaxValue - m_fMinValue)/(vDim.x-8);
			if ( m_fInterval > 0) {
				round = static_cast<int>( ((m_fCurrentValue-m_fMinValue)/m_fInterval)+.5f );
				m_fCurrentValue = round * m_fInterval;
			}
			if (m_fCurrentValue <= m_fMinValue) m_fCurrentValue = m_fMinValue;
			if (m_fCurrentValue >= m_fMaxValue) m_fCurrentValue = m_fMaxValue;
			updateSliderOffset();
		}
		return true;
	}

	return retval;
}

void Slider::setKnobSize(int w, int h)
{
	m_pKnob->setSize(w, h);
}

} // namespace
